/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * CameraViewController.java
 *
 * Created on Aug 7, 2011, 12:55:09 AM
 */
package pt.utl.ist.isr.livetrack.ui;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 *
 * @author David Miguel Antunes <davidmiguel [ at ] antunes.net>
 */
public class CameraViewController extends javax.swing.JPanel {

    public static interface CameraViewControllerObserver {

        public void stateChanged();

        public void acquireImage();
    }

    public static enum DisplayType {

        ACQUIRED,
        SUBTRACTED,
        BINARY,
        BACKGROUND
    }
    private Runnable aquisitionRunnable = new Runnable() {

        @Override
        public synchronized void run() {
            List<Future> futuresList = new ArrayList<Future>();

            for (final CameraViewControllerObserver cameraViewControllerObserver : observers) {
                futuresList.add(eservice.submit(new Callable<Void>() {

                    @Override
                    public Void call() throws Exception {
                        cameraViewControllerObserver.acquireImage();
                        return null;
                    }
                }));
            }

            for (Future future : futuresList) {
                try {
                    future.get();
                } catch (InterruptedException e) {
                } catch (ExecutionException e) {
                }
            }
//            for (CameraViewControllerObserver cameraViewControllerObserver : observers) {
//                cameraViewControllerObserver.acquireImage();
//            }
        }
    };
    private ArrayList<CameraViewControllerObserver> observers = new ArrayList<CameraViewControllerObserver>();
    private ExecutorService eservice = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    private Timer aquisitionTaskTimer;

    /** Creates new form CameraViewController */
    public CameraViewController() {
        initComponents();
    }

    public boolean isHighlightBlobsEnabled() {
        return highlightBlobsRadioButton.isSelected();
    }

    public boolean isTrackerOutputEnabled() {
        return trackerOutputRadioButton.isSelected();
    }

    public boolean isRoiEnabled() {
        return showRoiRadioButton.isSelected();
    }

    public int getAcquisitionPeriod() {
        return (Integer) acquisitionPeriodSpinner.getValue();
    }

    public DisplayType getDisplayType() {
        if (acquiredRadioButton.isSelected()) {
            return DisplayType.ACQUIRED;
        }
        if (subtractedRadioButton.isSelected()) {
            return DisplayType.SUBTRACTED;
        }
        if (binaryRadioButton.isSelected()) {
            return DisplayType.BINARY;
        }
        if (backgroundRadioButton.isSelected()) {
            return DisplayType.BACKGROUND;
        }
        throw new RuntimeException("bug");
    }

    private void forceAcquisition() {
        if (aquisitionTaskTimer == null) {
            aquisitionTaskTimer = new Timer();
            aquisitionTaskTimer.schedule(new TimerTask() {

                @Override
                public void run() {
                    aquisitionRunnable.run();
                }
            }, 0, getAcquisitionPeriod());
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jPanel2 = new javax.swing.JPanel();
        acquiredRadioButton = new javax.swing.JRadioButton();
        subtractedRadioButton = new javax.swing.JRadioButton();
        backgroundRadioButton = new javax.swing.JRadioButton();
        binaryRadioButton = new javax.swing.JRadioButton();
        highlightBlobsRadioButton = new javax.swing.JRadioButton();
        trackerOutputRadioButton = new javax.swing.JRadioButton();
        showRoiRadioButton = new javax.swing.JRadioButton();
        jPanel3 = new javax.swing.JPanel();
        forceAquisitionToggleButton = new javax.swing.JToggleButton();
        jLabel1 = new javax.swing.JLabel();
        acquisitionPeriodSpinner = new javax.swing.JSpinner();

        buttonGroup1.add(acquiredRadioButton);
        acquiredRadioButton.setSelected(true);
        acquiredRadioButton.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.acquiredRadioButton.text")); // NOI18N

        buttonGroup1.add(subtractedRadioButton);
        subtractedRadioButton.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.subtractedRadioButton.text")); // NOI18N

        buttonGroup1.add(backgroundRadioButton);
        backgroundRadioButton.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.backgroundRadioButton.text")); // NOI18N

        buttonGroup1.add(binaryRadioButton);
        binaryRadioButton.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.binaryRadioButton.text")); // NOI18N

        highlightBlobsRadioButton.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.highlightBlobsRadioButton.text")); // NOI18N

        trackerOutputRadioButton.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.trackerOutputRadioButton.text")); // NOI18N
        trackerOutputRadioButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                trackerOutputRadioButtonActionPerformed(evt);
            }
        });

        showRoiRadioButton.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.showRoiRadioButton.text")); // NOI18N

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(trackerOutputRadioButton)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addComponent(acquiredRadioButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(subtractedRadioButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(binaryRadioButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(backgroundRadioButton))
                    .addComponent(highlightBlobsRadioButton)
                    .addComponent(showRoiRadioButton))
                .addContainerGap(38, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(acquiredRadioButton)
                    .addComponent(subtractedRadioButton)
                    .addComponent(binaryRadioButton)
                    .addComponent(backgroundRadioButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(highlightBlobsRadioButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(trackerOutputRadioButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(showRoiRadioButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        forceAquisitionToggleButton.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.forceAquisitionToggleButton.text")); // NOI18N
        forceAquisitionToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                forceAquisitionToggleButtonActionPerformed(evt);
            }
        });

        jLabel1.setText(org.openide.util.NbBundle.getMessage(CameraViewController.class, "CameraViewController.jLabel1.text")); // NOI18N

        acquisitionPeriodSpinner.setModel(new javax.swing.SpinnerNumberModel(5, 5, 1000, 1));
        acquisitionPeriodSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                acquisitionPeriodSpinnerStateChanged(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(forceAquisitionToggleButton, javax.swing.GroupLayout.DEFAULT_SIZE, 171, Short.MAX_VALUE)
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(acquisitionPeriodSpinner)))
                .addContainerGap())
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(forceAquisitionToggleButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(acquisitionPeriodSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 67, Short.MAX_VALUE)
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );
    }// </editor-fold>//GEN-END:initComponents

    public Collection<CameraViewControllerObserver> getObservers() {
        return observers;
    }

    private void forceAquisitionToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_forceAquisitionToggleButtonActionPerformed

        if (forceAquisitionToggleButton.isSelected()) {
            forceAcquisition();
        } else {
            if (aquisitionTaskTimer != null) {
                aquisitionTaskTimer.cancel();
                aquisitionTaskTimer = null;
            }
        }
}//GEN-LAST:event_forceAquisitionToggleButtonActionPerformed

    private void acquisitionPeriodSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_acquisitionPeriodSpinnerStateChanged
        if (forceAquisitionToggleButton.isSelected()) {

            if (aquisitionTaskTimer != null) {
                aquisitionTaskTimer.cancel();
                aquisitionTaskTimer = null;
                forceAcquisition();
            }
        }
}//GEN-LAST:event_acquisitionPeriodSpinnerStateChanged

    private void trackerOutputRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_trackerOutputRadioButtonActionPerformed
    }//GEN-LAST:event_trackerOutputRadioButtonActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JRadioButton acquiredRadioButton;
    private javax.swing.JSpinner acquisitionPeriodSpinner;
    private javax.swing.JRadioButton backgroundRadioButton;
    private javax.swing.JRadioButton binaryRadioButton;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JToggleButton forceAquisitionToggleButton;
    private javax.swing.JRadioButton highlightBlobsRadioButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JRadioButton showRoiRadioButton;
    private javax.swing.JRadioButton subtractedRadioButton;
    private javax.swing.JRadioButton trackerOutputRadioButton;
    // End of variables declaration//GEN-END:variables
}
